﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Flurl.Http;
using Newtonsoft.Json.Linq;
using Pay.Core;
using Pay.DTO;
using Pay.IService;
using Pay.TO;

namespace Pay.Service {
	public class kyPayService : ServiceBase2, IPayService, IDisposable {
		private kySign _kySign;
		private IMerchantService _iMerchantService;
		private ISettingService _iSettingService;
		private IChargeService _iChargeService;
		private IProfitDayService _iProfitDayService;
		private IBillService _iBillService;
		private IPayHtmlService _iPayHtmlService;

		public kyPayService(IUnitOfWork iUnitOfWork, ISettingService iSettingService,
						   IMerchantService iMerchantService, IChargeService iChargeService,
						IProfitDayService iProfitDayService, IBillService iBillService,
						   IPayHtmlService iPayHtmlService) : base(iUnitOfWork) {
			_iSettingService = iSettingService;
			_iMerchantService = iMerchantService;
			_iChargeService = iChargeService;
			_iProfitDayService = iProfitDayService;
			_iBillService = iBillService;
			_iPayHtmlService = iPayHtmlService;
			_kySign = new kySign();
		}
		public Task<transfer_result> AgencyFund(apply_receive model) {
			throw new NotImplementedException();
		}

		public int DealItp(long id) {
			throw new NotImplementedException();
		}

		public Task<gateway_pay_result> GatewayPay(gateway_pay_model model) {
			throw new NotImplementedException();
		}

		public List<type_setting> GatewayPayBank() {
			throw new NotImplementedException();
		}

		public Task<pay_notity> GatewayPayQuery(refund_model_query model) {
			throw new NotImplementedException();
		}

		public Task<refund_result> GatewayPayRefund(refund_model model) {
			throw new NotImplementedException();
		}

		public Task<refund_result> GatewayRefundQuery(refund_model_query model) {
			throw new NotImplementedException();
		}

		public Task<ApiResultMessage> InsteadReceive(verify_model_sms model) {
			throw new NotImplementedException();
		}

		public Task<ApiResultMessage> InsteadReceive(verify_model model) {
			throw new NotImplementedException();
		}

		public Task<int> ItpToFile(DateTime create_date) {
			throw new NotImplementedException();
		}

		public Task<merchant_register_result> MerchantModify(long bind_id, string settle_type,PayChannel channel = PayChannel.None) {
			throw new NotImplementedException();
		}

		public Task<merchant_register_result> MerchantRegister(long bind_id, string settle_type,PayChannel channel = PayChannel.None) {
			throw new NotImplementedException();
		}

		public Task<merchant_register_result> MerchantRegister(merchant_register_model dto, string opt) {
			throw new NotImplementedException();
		}

		public Task<native_result> NativePay(native_model model) {
			throw new NotImplementedException();
		}

		public async Task<string> Notify(string merchant_no, string order_no) {
			string result = string.Empty;
			charge_dto order = _iChargeService.Get(merchant_no, order_no);
			if (order == null) return "OK";
			try {
				var data = new pay_notity {
					tran_amount = ((int)(order.order_amount * 100)).ToString(), order_no = order.order_no, transaction_no = order.pay_info.transaction_no,
					pay_time = order.pay_info.pay_time.HasValue ? order.pay_info.pay_time.Value : order.order_time,
					status = (order.status == ChargeStatus.Finish ? 1 : 2)
				};
				//失败的要再查询通道判断是否真失败,处理掉单
				if (order.status != ChargeStatus.Finish) {
					var pay_model = new ky_head_query { ver = "1.0.4", trans_id = order.order_no, random = DtoHelper.GuidTo16String() };
					var hfResult = await _kySign.PayGateway2(pay_model);
					if (hfResult != null) {
						if (hfResult.Status == 1) {
							if (hfResult.TheState == 2) {
								var pay_time = DateTime.Parse(hfResult.TransactionCloseTime);
								data.status = 1;
								_iChargeService.FailOrUnConfirmToSuceess(merchant_no, order.order_no, pay_time);
							}
						}
					}
				}
				data.result_msg = (data.status == 1 ? "支付成功" : order.fail);
				if (string.IsNullOrEmpty(order.notify)) return "OK";
				var notify_result = await order.notify.PostJsonAsync(ApiResultToJson.Json(data)).ReceiveJson<ResultMessage<string>>();
				result = notify_result.data;
				var log = IocHelper.Get<ILogHelper>("info");
				log.Info(order.order_no + ":" + notify_result.ToJson());
			} catch (Exception ex) {
				var log = IocHelper.Get<ILogHelper>("info");
				log.Error("订单通道查询异常:" + order.order_no);
				string message = string.Format("消息类型：{0}\r\n消息内容：{1}\r\n引发异常的方法：{2}\r\n引发异常源：{3}"
								, ex.GetType().Name, ex.Message, ex.TargetSite, ex.Source + ex.StackTrace);
				log.Error(message);
			}
			return result;
		}

		public Task<string> NotifyTransfer(string merchant_no, string order_no) {
			throw new NotImplementedException();
		}

		#region 快捷同卡同出
		public Task<quick_pay_result> QuickPay(quick_sms_model model) {
			throw new NotImplementedException();
		}

		/// <summary>
		/// 快捷支付
		/// </summary>
		/// <returns>The receive.</returns>
		/// <param name="model">Model.</param>
		public async Task<quick_pay_result> QuickPay(quick_pay_model model) {
			var setting = _iSettingService.Get();
			var binder = _iMerchantService.Get(model.bind_no);
			string pay_code = model.pay_code;
			model.settle_type = "T0";
            var binder_payments = _iMerchantService.GetPayments(binder.id);
            var payment = binder_payments.FirstOrDefault(c => c.payment.channel == model.pay_channel);
			var settle = payment.settles.First(c => c.settle_type == model.settle_type && c.code == pay_code);
			//同进件数据比较是否一致
			if (model.settle_fee / 100M != settle.settle)
				return await ApiResultToJson.JsonAsync<quick_pay_result>("结算费与商户进件的结算费不同", 2001);
			if (model.fee != settle.fee)
				return await ApiResultToJson.JsonAsync<quick_pay_result>("费率与商户进件的费率不同", 2001);
			if (model.pay_fee_amount != (int)Math.Ceiling(decimal.Parse(model.tran_amount) * model.fee))
				return await ApiResultToJson.JsonAsync<quick_pay_result>("实扣费率金额不正确");
			//把商户请求转为通道请求消息
			var id = Guid.NewGuid().ToString("N");
			var notify = setting.site.api_url + "/pay/ky_back_notify/" + id;
			//var notify = "http://testapi.epalpay.com/pay/ky_back_notify/" + id;
			var front_notify_url = model.front_notify;
			var authinfo = binder.setting.auth_info;
			var pay_model = new ky_quick {
				body = "购买商品付款", random = model.nonce, trans_id = model.order_no, paychannelcode = "t0",
				notify_url = notify, fronturl = front_notify_url, bankname = authinfo.bank_name, banknum = authinfo.account_no,
				name = authinfo.account_name, idcard = authinfo.id_card, paybanknum = model.account_no, money = model.tran_amount,
				userfee = ((int)(model.pay_fee_amount + model.settle_fee)).ToString(), clearnotifyurl = "", drbankcode = "", userappcode = ""
			};
			//调用通道执行并处理返回，请通道响应消息封装为平台响应商户消息
			var html = _kySign.PayGateway(pay_model);
			if (!string.IsNullOrEmpty(html)) {
				var charge = _iChargeService.AddByQuickPay(model);
				//将HTML保存到mongodb
				var ok = _iPayHtmlService.Save(new pay_html_dto { id = id, html = html, merchant_no = model.merchant_no, order_no = model.order_no, charge = charge.ToJson() });
				if (ok) {
					var requestUrl = html;
					return await ApiResultToJson.JsonAsync("鉴权成功，待确认支付", new quick_pay_result {
						order_no = model.order_no, protocol_no = "", request_url = requestUrl,
						pay_time = DateTime.Now, transaction_no = "", status = 3
					});
				} else
					return await ApiResultToJson.JsonAsync<quick_pay_result>("支付页面加载失败");
			}
			return await ApiResultToJson.JsonAsync<quick_pay_result>("异常支付");
		}

		/// <summary>
		/// 快捷支付查询
		/// </summary>
		/// <returns>The pay query.</returns>
		/// <param name="model">Model.</param>
		public async Task<pay_notity> QuickPayQuery(refund_model_query model) {
			charge_dto order = null;
			var data = new pay_notity { status = 2, order_no = model.order_no };
			if (!string.IsNullOrEmpty(model.order_no)) order = _iChargeService.Get(model.merchant_no, model.order_no);
			if (order == null) {
				var obj = _iPayHtmlService.Get(model.merchant_no, model.order_no);
				if (obj != null) {
					var pay_model = new ky_head_query { ver = "1.0.4", trans_id = obj.order_no, random = model.nonce };
					var hfResult = await _kySign.PayGateway2(pay_model);
					if (hfResult != null) {
						var charge = obj.charge.ToObject<charge_dto>();
						if (hfResult.Status == 1) {
							if (hfResult.TheState == 2) {
								var pay_time = DateTime.Parse(hfResult.TransactionCloseTime);
								data.status = 1; data.pay_time = pay_time; data.result_msg = "支付成功"; data.tran_amount = ((int)charge.amount * 100).ToString();
								var result = _iChargeService.PaySuceess(obj, data.order_no, data.pay_time);
								if (result > 0) {
									var notifyResult = await Notify(charge.merchant_no, model.order_no);
									_iPayHtmlService.Remove(obj.id);
								}
							} else {
								data.result_code = 1001; data.result_msg = "支付中";
								data.pay_time = obj.create_time; data.tran_amount = ((int)charge.amount * 100).ToString();
							}
						} else {
							data.result_code = 1001; data.result_msg = hfResult.Msg;
							data.pay_time = obj.create_time; data.tran_amount = ((int)charge.amount * 100).ToString();
						}
					}
				} else {
					data.result_code = 1001; data.result_msg = "支付失败";
				}
			} else {
				data.status = order.status == ChargeStatus.Finish ? 1 : 2; data.pay_time = order.order_time; data.transaction_no = order.order_no;
				data.result_msg = order.status == ChargeStatus.Finish ? "支付成功" : "支付失败"; data.tran_amount = ((int)order.amount * 100).ToString();
				if (order.status != ChargeStatus.Finish) data.result_code = 1001;
			}
			return data;
		}

		public Task<refund_result> QuickPayRefund(refund_model model) {
			throw new NotImplementedException();
		}

		public Task<refund_result> QuickPayRefundQuery(refund_model_query model) {
			throw new NotImplementedException();
		}

		public Task<ApiResultMessage> QuickPaySendsms(quick_sendsms_model model) {
			throw new NotImplementedException();
		}
		#endregion

		public Task<quota_result> Quota(string merchant_no, string busiType) {
			throw new NotImplementedException();
		}

		public Task<transfer_result> ReTransfer(long id) {
			throw new NotImplementedException();
		}

		public Task<batch_transfer_result> Transfer(batch_transfer model) {
			throw new NotImplementedException();
		}

		public Task<transfer_result> Transfer(apply_transfer model) {
			throw new NotImplementedException();
		}

		public Task<int> TransferBack(long batchId, string noticeTranId, long merchant_id) {
			throw new NotImplementedException();
		}

		public Task<int> TransferNotify(long batchId, string batchFileName, long merchant_id) {
			throw new NotImplementedException();
		}

		public Task<transfer_result> TransferQuery(transfer_query model) {
			throw new NotImplementedException();
		}
		/// <summary>
		/// 四要素认证
		/// </summary>
		/// <param name="model"></param>
		/// <returns></returns>
		public async Task<certify_verify_result> CertifyVerify(certify_verify model) {
			var supportBanks = BankListData();
			if (!supportBanks.Keys.Contains(model.bank_code)) {
				return await ApiResultToJson.JsonAsync<certify_verify_result>("四要素认证不支持该银行");
			}
			var kyData = new ky_certify_verify_model {
				ACC_NAME = model.account_name, ACC_NO = model.account_no, CARD_TYPE = model.card_type.ToString(), CERT_NO = model.id_card,
				IPS_CODE = "IP1001", VERSION = "1.0.2", MER_REQ_SEQ = model.order_no, VERIFY_TYPE = model.verify_type
			};
			var response = await _kySign.PayGateway<ky_certify_verify_result>(kyData);
			if (response != null) {
				if (response.res_code == "0000") {
					if (response.res_type == "S" && response.validate_status == "00") {
						model.status = CertifyStatus.Auth;
						_iMerchantService.CertifyVerify(model, response.res_msg);
						return await ApiResultToJson.JsonAsync("认证成功", new certify_verify_result { status = AuthStatusEnum.Auth });
					} else if (response.res_type == "R") {
						model.status = CertifyStatus.UnConfirm;
						_iMerchantService.CertifyVerify(model, response.res_msg);
						return await ApiResultToJson.JsonAsync("认证成功，待确认", new certify_verify_result { status = AuthStatusEnum.Wait });
					} else {
						model.status = CertifyStatus.Fail;
						_iMerchantService.CertifyVerify(model, response.res_msg);
						return await ApiResultToJson.JsonAsync("认证失败", new certify_verify_result { status = AuthStatusEnum.Fail });
					}
				}
			}
			return await ApiResultToJson.JsonAsync("认证失败", new certify_verify_result { status = AuthStatusEnum.Wait });
		}

		/// <summary>
		/// 支持银行列表数据
		/// </summary>
		/// <returns></returns>
		private Dictionary<string, string> BankListData() {
			var banks = new Dictionary<string, string>();
			banks.Add("ICBC", "01020000");
			banks.Add("ABC", "01030000");
			banks.Add("CCB", "01050000");
			banks.Add("BOC", "01040000");
			banks.Add("PSBC", "01000000");
			banks.Add("CMB", "03080000");
			banks.Add("CEB", "03030000");
			banks.Add("CGB", "03060000");
			banks.Add("HXB", "03040000");
			banks.Add("CIB", "03090000");
			banks.Add("CITIC", "03020000");
			banks.Add("PAB", "03070000");
			banks.Add("BCM", "03010000");
			banks.Add("SPDB", "03100000");
			return banks;
		}

		public Task<mall_result> MallPay(mall_model obj) {
			throw new NotImplementedException();
		}

        public Task<transfer_result> TokenTransfer(long id) {
            throw new NotImplementedException();
        }

        public Task<transfer_result> TokenTransferQuery(transfer_query model) {
            throw new NotImplementedException();
        }
    }
}
